import * as THREE from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
import Tile from './Tile'
import {
  getPxFromLngLat,
  getTileRowAndCol,
  lngLat2Mercator,
  TILE_SIZE,
} from "@/utils/utils.js";

class ZMapGL {
  constructor(el, options) {
    const mountEl = document.getElementById(el)
    const { width, height } = mountEl.getBoundingClientRect()
    this.width = width
    this.height = height
    this.mountEl = mountEl
    // 设置默认的坐标原点和缩放比例
    this.options = {
      center: [0, 0],
      zoom: 16,
      ...options
    }
    this.minZoom = 3
    this.maxZoom = 18
    // 存储缓存的瓦片
    this.tileCache = {}
    // 创建绘制瓦片的render
    const { render, scene, camera } = this.initScene()
    this.render = render
    this.scene = scene
    this.camera = camera
    //  绘制瓦片
    this.renderTile()
    // 添加事件移动和缩放事件
    this.addEvent()
  }
  initScene() {
    const scene = new THREE.Scene();
    const camera = new THREE.OrthographicCamera(
      this.width / -2,
      this.width / 2,
      this.height / 2,
      this.height / -2,
      1,
      1000
    );
    camera.position.set(0, 0, 55);
    camera.lookAt(0, 0, 0);
    const render = new THREE.WebGLRenderer();
    render.setSize(this.width, this.height);
    this.mountEl.appendChild(render.domElement);
    render.render(scene, camera);

    const control = new OrbitControls(camera, render.domElement);
    control.target.set(0, 0, 0);
    control.update();

    function animate() {
      render.render(scene, camera)
      requestAnimationFrame(animate)
    }

    animate()

    return { render, scene, camera }
  }

  renderTile() {
    const { center, zoom } = this.options;
    // 获取中心点瓦片行列号
    const centerTile = getTileRowAndCol(...lngLat2Mercator(...center), zoom);
    // 中心瓦片中心的像素坐标
    const centerTilePxPos = [
      centerTile[0] * TILE_SIZE + TILE_SIZE / 2,
      centerTile[1] * TILE_SIZE + TILE_SIZE / 2,
    ];
    // 中心点像素坐标，（canvas原点位置）
    const centerPxPos = getPxFromLngLat(...center, zoom);
    //中心像素坐标距中心瓦片差值
    const offset = [
      centerTilePxPos[0] - centerPxPos[0],
      centerTilePxPos[1] - centerPxPos[1],
    ];

    // 绘制范围内的所有瓦片
    const offsetAbs = offset.map((s) => Math.abs(s));
    // 计算瓦片数量
    let rowMinNum = Math.ceil(
      (this.width / 2 - offsetAbs[0] - TILE_SIZE / 2) / TILE_SIZE
    ); // 左
    let colMinNum = Math.ceil(
      (this.height / 2 - offsetAbs[1] - TILE_SIZE / 2) / TILE_SIZE
    ); // 上
    let rowMaxNum = Math.ceil(
      (this.width / 2 - (TILE_SIZE / 2 - offsetAbs[0])) / TILE_SIZE
    ); // 右
    let colMaxNum = Math.ceil(
      (this.height / 2 - (TILE_SIZE / 2 - offsetAbs[1])) / TILE_SIZE
    ); // 下

    // 从上到下，从左到右，加载瓦片
    for (let i = -rowMinNum; i <= rowMaxNum; i++) {
      for (let j = -colMinNum; j <= colMaxNum; j++) {
        // 加载瓦片图片
        // 瓦片行向右增加，threeJs坐标x轴也是向右增加，加一行x坐标就是加 i*TILE_SIZE
        // 瓦片列向下增加，threeJs坐标y轴是向上增加，加一列Y坐标是要减去j*TILE_SIZE
        const x = i * TILE_SIZE + offset[0];
        const y = offset[1] - j * TILE_SIZE;
        const row = centerTile[0] + i; // 行号
        const col = centerTile[1] + j; // 列号
        const cacheKey = `${row}-${col}-${zoom}`;
        if (this.tileCache[cacheKey]) {
          this.tileCache[cacheKey].updatePos(x, y).render();
        } else {
          this.tileCache[cacheKey] = new Tile({
            ctx: this.scene,
            x,
            y,
            row,
            col,
            zoom,
          });
        }
      }
    }
  }
  addEvent() {

  }
}

export default ZMapGL